﻿using System;
using Microsoft.Xna.Framework;

namespace SunXNA.RainbowXNA
{
    class OBB
    {
        private Vector3[] m_points;

        public OBB()
        {
            m_points = new Vector3[8];
        }

        public static OBB CreateFromBox(BoundingBox box)
        {
            Vector3 v3Min = box.Min;
            Vector3 v3Max = box.Max;
            return CreateFromMinMax(ref v3Min, ref v3Max);
        }

        public static OBB CreateFromMinMax(ref Vector3 v3Min, ref Vector3 v3Max)
        {
            OBB newObb = new OBB();

            //0,0,0
            newObb.m_points[0] = v3Min;

            //0,0,1
            newObb.m_points[1].X = v3Min.X;
            newObb.m_points[1].Y = v3Min.Y;
            newObb.m_points[1].Z = v3Max.Z;

            //1,0,1
            newObb.m_points[2].X = v3Max.X;
            newObb.m_points[2].Y = v3Min.Y;
            newObb.m_points[2].Z = v3Max.Z;

            //1,0,0
            newObb.m_points[3].X = v3Max.X;
            newObb.m_points[3].Y = v3Min.Y;
            newObb.m_points[3].Z = v3Min.Z;

            //0,1,0
            newObb.m_points[4].X = v3Min.X;
            newObb.m_points[4].Y = v3Max.Y;
            newObb.m_points[4].Z = v3Min.Z;

            //0,1,1
            newObb.m_points[5].X = v3Min.X;
            newObb.m_points[5].Y = v3Max.Y;
            newObb.m_points[5].Z = v3Max.Z;

            //1,1,1
            newObb.m_points[6] = v3Max;

            //1,1,0
            newObb.m_points[7].X = v3Max.X;
            newObb.m_points[7].Y = v3Max.Y;
            newObb.m_points[7].Z = v3Min.Z;

            return newObb;
        }

        public BoundingBox ToBoundingBox()
        {
            BoundingBox bb;

            bb.Max = bb.Min = m_points[0];

            foreach (Vector3 point in m_points)
            {
                if (point.X < bb.Min.X)
                {
                    bb.Min.X = point.X;
                }

                if (point.Y < bb.Min.Y)
                {
                    bb.Min.Y = point.Y;
                }

                if (point.Z < bb.Min.Z)
                {
                    bb.Min.Z = point.Z;
                }

                if (point.X > bb.Max.X)
                {
                    bb.Max.X = point.X;
                }

                if (point.Y > bb.Max.Y)
                {
                    bb.Max.Y = point.Y;
                }

                if (point.Z > bb.Max.Z)
                {
                    bb.Max.Z = point.Z;
                }
            }

            return bb;
        }

        public OBB Transform(ref Matrix m4Transform)
        {
            OBB outObb = new OBB();

            for (int i = 0; i < 8; ++i)
            {
                Vector3.Transform(ref m_points[i],
                                  ref m4Transform,
                                  out outObb.m_points[i]);
            }

            return outObb;
        }
    }
}
